home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 2_3 / pcmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-20  |  12.1 KB  |  604 lines

  1. /*    SCCS Id: @(#)pcmain.c    2.3    87/12/12
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* main.c - (PC) version */
  4.  
  5. #include <stdio.h>
  6. #include <signal.h>
  7. #include "hack.h"
  8.  
  9. #ifdef QUEST
  10. #define    gamename    "PC NetQuest"
  11. #else
  12. #define    gamename    "PC NetHack"
  13. #endif
  14.  
  15. char orgdir[PATHLEN], *getcwd();
  16.  
  17. extern struct permonst mons[CMNUM+2];
  18. extern char genocided[], fut_geno[];
  19. extern char *getlogin(), *getenv();
  20. extern char plname[PL_NSIZ], pl_character[PL_CSIZ];
  21.  
  22. int (*afternmv)(), done1(), (*occupation)();
  23.  
  24. char SAVEF[FILENAME];
  25. char *hname = gamename;
  26. char obuf[BUFSIZ];    /* BUFSIZ is defined in stdio.h */
  27. int hackpid;        /* not used anymore, but kept in for save files */
  28.  
  29. extern char *nomovemsg;
  30. extern long wailmsg;
  31.  
  32. main(argc,argv)
  33. int argc;
  34. char *argv[];
  35. {
  36.     register int fd;
  37.     register char *dir;
  38.     extern struct monst *makedog();
  39. #ifdef MSDOS
  40.     static void moveloop();    /* a helper function for MSC optimizer */
  41.  
  42.     /* Save current directory and make sure it gets restored when
  43.      * the game is exited.
  44.      */
  45.     int (*funcp)();
  46.  
  47.     if (getcwd(orgdir, sizeof orgdir) == NULL) {
  48.         xputs("NetHack: current directory path too long\n");
  49.         _exit(1);
  50.     }
  51.     funcp = exit;    /* Kludge to get around LINT_ARGS of signal.
  52.              * This will produce a compiler warning, but that's OK.
  53.              */
  54.     signal(SIGINT, funcp);    /* restore original directory */
  55. #endif
  56.  
  57. #ifdef GRAPHICS
  58.     /* Set the default values of the presentation characters */
  59.     memcpy((char *) &showsyms, (char *) &defsyms, sizeof(struct symbols));
  60. #endif
  61. #ifdef DGK
  62.     if ((dir = getenv("HACKDIR")) != (char *) NULL) {
  63.         (void) strcpy(hackdir, dir);
  64.         chdirx (dir, 1);
  65.     }
  66.     zero_finfo();
  67.     initoptions();
  68.     if (!hackdir[0])
  69.         (void) strcpy(hackdir, orgdir);
  70.     dir = hackdir;
  71. #else
  72.     dir = getenv("HACKDIR");
  73.     if(argc > 1 && !strncmp(argv[1], "-d", 2)) {
  74.         argc--;
  75.         argv++;
  76.         dir = argv[0]+2;
  77.         if(*dir == '=' || *dir == ':') dir++;
  78.         if(!*dir && argc > 1) {
  79.             argc--;
  80.             argv++;
  81.             dir = argv[0];
  82.         }
  83.         if(!*dir)
  84.             error("Flag -d must be followed by a directory name.");
  85.     }
  86. #endif /* DGK */
  87.  
  88.     /*
  89.      * Now we know the directory containing 'record' and
  90.      * may do a prscore().
  91.      */
  92.     if(argc > 1 && !strncmp(argv[1], "-s", 2)) {
  93.         chdirx(dir,0);
  94.         prscore(argc, argv);
  95.         exit(0);
  96.     }
  97.  
  98.     /*
  99.      * It seems he really wants to play.
  100.      * Remember tty modes, to be restored on exit.
  101.      */
  102.     gettty();
  103.     setbuf(stdout,obuf);
  104.     setrandom();
  105.     startup();
  106.     init_corpses();    /* initialize optional corpse names */
  107.     cls();
  108.     u.uhp = 1;    /* prevent RIP on early quits */
  109.     u.ux = FAR;    /* prevent nscr() */
  110.  
  111.     /*
  112.      * We cannot do chdir earlier, otherwise gethdate will fail.
  113.      */
  114.     chdirx(dir,1);
  115.  
  116.     /*
  117.      * Process options.
  118.      */
  119.     while(argc > 1 && argv[1][0] == '-'){
  120.         argv++;
  121.         argc--;
  122.         switch(argv[0][1]){
  123. #ifdef WIZARD
  124.         case 'D':
  125. # ifdef MSDOS
  126.             wizard = TRUE;
  127. # else
  128.             if(!strcmp(getlogin(), WIZARD))
  129.                 wizard = TRUE;
  130.             else {
  131.                 settty("Sorry, you can't operate in debug mode.\n");
  132.                 clearlocks();
  133.                 exit(0);
  134.             }
  135. # endif
  136.             break;
  137. #endif
  138.         case 'u':
  139.             if(argv[0][2])
  140.               (void) strncpy(plname, argv[0]+2, sizeof(plname)-1);
  141.             else if(argc > 1) {
  142.               argc--;
  143.               argv++;
  144.               (void) strncpy(plname, argv[0], sizeof(plname)-1);
  145.             } else
  146.                 printf("Player name expected after -u\n");
  147.             break;
  148. #ifdef DGK
  149.         /* Person does not want to use a ram disk
  150.          */
  151.         case 'R':
  152.             ramdisk = FALSE;
  153.             break;
  154. #endif
  155.         default:
  156.             /* allow -T for Tourist, etc. */
  157.             (void) strncpy(pl_character, argv[0]+1,
  158.                 sizeof(pl_character)-1);
  159.  
  160.             /* printf("Unknown option: %s\n", *argv); */
  161.         }
  162.     }
  163.  
  164. #ifdef DGK
  165.     set_lock_and_bones();
  166.     copybones(FROMPERM);
  167. #endif
  168. #ifdef WIZARD
  169.     if (wizard)
  170.         (void) strcpy(plname, "wizard");
  171.     else
  172. #endif
  173.     if (!*plname)
  174.         askname();
  175.     plnamesuffix();        /* strip suffix from name; calls askname() */
  176.                 /* again if suffix was whole name */
  177.                 /* accepts any suffix */
  178. #ifdef WIZARD
  179.     if(wizard) {
  180.         register char *sfoo;
  181. # ifndef DGK
  182.         /* lock is set in read_config_file */
  183.         (void) strcpy(lock,plname);
  184. # endif
  185.         if(sfoo = getenv("MAGIC"))
  186.             while(*sfoo) {
  187.                 switch(*sfoo++) {
  188.                 case 'n': (void) srand(*sfoo++);
  189.                     break;
  190.                 }
  191.             }
  192.         if(sfoo = getenv("GENOCIDED")){
  193.             if(*sfoo == '!'){
  194.                 register struct permonst *pm = mons;
  195.                 register char *gp = genocided;
  196.  
  197.                 while(pm < mons+CMNUM+2){
  198.                     if(!index(sfoo, pm->mlet))
  199.                         *gp++ = pm->mlet;
  200.                     pm++;
  201.                 }
  202.                 *gp = 0;
  203.             } else
  204.                 (void) strcpy(genocided, sfoo);
  205.             (void) strcpy(fut_geno, genocided);
  206.         }
  207.     }
  208. #endif /* WIZARD */
  209.     start_screen();
  210. #ifdef DGK
  211.     strncat(SAVEF, plname, 8);
  212.     strcat(SAVEF, ".sav");
  213.     cls();
  214.     if (saveDiskPrompt(1) && ((fd = open(SAVEF, 0)) >= 0) &&
  215.        (uptodate(fd) || !unlink(SAVEF))) {
  216. #else 
  217.     (void) sprintf(SAVEF, "save/%d%s", getuid(), plname);
  218.     regularize(SAVEF+5);        /* avoid . or / in name */
  219.     if((fd = open(SAVEF,0)) >= 0 &&
  220.        (uptodate(fd) || unlink(SAVEF) == 666)) {
  221. #endif /* DGK */
  222.         (void) signal(SIGINT,done1);
  223.         pline("Restoring old save file...");
  224.         (void) fflush(stdout);
  225.         if(!dorecover(fd))
  226.             goto not_recovered;
  227.         pline("Hello %s%s, welcome to %s!", 
  228.             (Badged) ? "Officer " : "", plname, hname);
  229. #ifdef WIZARD
  230.         if (wizard && dlevel == 1)
  231. # ifdef STOOGES
  232. pline ("The wiz is at %d, the medusa is at %d, and the stooges are at %d",
  233.             u.wiz_level, u.medusa_level, u.stooge_level);
  234. # else
  235.                 pline ("The wiz is at %d, and the medusa at %d",
  236.                u.wiz_level, u.medusa_level);
  237. # endif
  238. #endif
  239.         flags.move = 0;
  240.     } else {
  241. not_recovered:
  242. #ifdef DGK
  243.         gameDiskPrompt();
  244. #endif
  245.         fobj = fcobj = invent = 0;
  246.         fmon = fallen_down = 0;
  247.         ftrap = 0;
  248.         fgold = 0;
  249.         flags.ident = 1;
  250.         init_objects();
  251.         u_init();
  252.  
  253.         (void) signal(SIGINT,done1);
  254.         mklev();
  255.         u.ux = xupstair;
  256.         u.uy = yupstair;
  257.         (void) inshop();
  258.         setsee();
  259.         flags.botlx = 1;
  260.         /* Fix bug with dog not being made because a monster
  261.          * was on the level 1 staircase
  262.          */
  263.         {
  264.             struct monst *mtmp;
  265.  
  266.             if (mtmp = m_at(u.ux, u.uy))
  267.                 mnexto(mtmp);
  268.         }
  269.         makedog();
  270.         { register struct monst *mtmp;
  271.           if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp);    /* riv05!a3 */
  272.         }
  273.         seemons();
  274.         docrt();
  275.  
  276.         /* give welcome message before pickup messages */
  277.         pline("Hello %s, welcome to %s!", plname, hname);
  278.  
  279.         pickup(1);
  280.         read_engr_at(u.ux,u.uy);
  281.         flags.move = 1;
  282.     }
  283.     flags.moonphase = phase_of_the_moon();
  284.     if(flags.moonphase == FULL_MOON) {
  285.         pline("You are lucky! Full moon tonight.");
  286.         if(!u.uluck) change_luck(1);
  287.     } else if(flags.moonphase == NEW_MOON) {
  288.         pline("Be careful! New moon tonight.");
  289.     }
  290.  
  291.     initrack();
  292.     (void) signal(SIGINT, SIG_IGN);
  293. #ifdef MSDOS
  294.     /* Help for Microsoft optimizer.  Otherwise main is too large -dgk*/
  295.     moveloop();
  296. }
  297.  
  298. static void
  299. moveloop()
  300. {
  301.     char ch;
  302.     int abort;
  303. #endif /* MSDOS */
  304.     for(;;) {
  305.         if(flags.move) {    /* actual time passed */
  306.  
  307.             settrack();
  308.  
  309.             if(moves%2 == 0 ||
  310.               (!(Fast & ~INTRINSIC) && (!Fast || rn2(3)))) {
  311.                 extern struct monst *makemon();
  312.                 movemon();
  313. #ifdef HARD
  314.                 if(!rn2(u.udemigod?25:(dlevel>30)?50:70))
  315. #else
  316.                 if(!rn2(70))
  317. #endif
  318.                     (void) makemon((struct permonst *)0, 0, 0);
  319.             }
  320.             if(Glib) glibr();
  321.             timeout();
  322.             ++moves;
  323. #ifdef PRAYERS
  324.             if (u.ublesscnt)  u.ublesscnt--;
  325. #endif
  326. #ifndef DGK
  327.             if(flags.time) flags.botl = 1;
  328. #endif
  329. #ifdef KAA
  330.             if(u.mtimedone)
  331.                 if(u.mh < 1) rehumanize();
  332.             else
  333. #endif
  334.                 if(u.uhp < 1) {
  335.                 pline("You die...");
  336.                 done("died");
  337.                 }
  338.             if(u.uhp*10 < u.uhpmax && moves-wailmsg > 50){
  339.                 wailmsg = moves;
  340. #ifdef KAA
  341.                 if(index("WEV", pl_character[0])) {
  342.                     if (u.uhp == 1)
  343.                        pline("%s is about to die.", pl_character);
  344.                     else
  345.                        pline("%s, your life force is running out.",
  346.                         pl_character);
  347.                 } else {
  348. #endif
  349.                 if(u.uhp == 1)
  350.                 pline("You hear the wailing of the Banshee...");
  351.                 else
  352.                 pline("You hear the howling of the CwnAnnwn...");
  353. #ifdef KAA
  354.                 }
  355. #endif
  356.             }
  357. #ifdef KAA
  358.             if (u.mtimedone) {
  359.                 if (u.mh < u.mhmax) {
  360.                 if (Regeneration || !(moves%20)) {
  361.                     flags.botl = 1;
  362.                     u.mh++;
  363.                 }
  364.                 }
  365.             }
  366. #endif
  367.             if(u.uhp < u.uhpmax) {
  368.                 if(u.ulevel > 9) {
  369.                     if(HRegeneration || !(moves%3)) {
  370.                         flags.botl = 1;
  371.                         u.uhp += rnd((int) u.ulevel-9);
  372.                         if(u.uhp > u.uhpmax)
  373.                         u.uhp = u.uhpmax;
  374.                     }
  375.                 } else if(HRegeneration ||
  376.                     (!(moves%(22-u.ulevel*2)))) {
  377.                     flags.botl = 1;
  378.                     u.uhp++;
  379.                 }
  380.             }
  381. #ifdef SPELLS
  382.             if ((u.uen<u.uenmax) && (!(moves%(21-u.ulevel/2)))) {
  383.                 u.uen += rn2(u.ulevel/4 + 1) + 1;
  384.                 if (u.uen > u.uenmax)  u.uen = u.uenmax;
  385.                 flags.botl = 1;
  386.             }
  387. #endif
  388.             if(Teleportation && !rn2(85)) tele();
  389. #if defined(KAA) && defined(BVH)
  390.             if(Polymorph && !rn2(100)) polyself();
  391. #endif
  392.             if(Searching && multi >= 0) (void) dosearch();
  393.             gethungry();
  394.             invault();
  395.             amulet();
  396. #ifdef HARD
  397.             if (!rn2(50+(u.ulevel*3))) u_wipe_engr(rnd(3));
  398.             if (u.udemigod) {
  399.  
  400.                 u.udg_cnt--;
  401.                 if(u.udg_cnt <= 0) {
  402.  
  403.                     intervene();
  404.                     u.udg_cnt = rn1(200, 50);
  405.                 }
  406.             }
  407. #endif
  408.         }
  409.         if(multi < 0) {
  410.             if(!++multi){
  411.                 pline(nomovemsg ? nomovemsg :
  412.                     "You can move again.");
  413.                 nomovemsg = 0;
  414.                 if(afternmv) (*afternmv)();
  415.                 afternmv = 0;
  416.             }
  417.         }
  418.  
  419.         find_ac();
  420. #ifndef QUEST
  421.         if(!flags.mv || Blind)
  422. #endif
  423.         {
  424.             seeobjs();
  425.             seemons();
  426.             nscr();
  427.         }
  428. #ifdef DGK
  429.         if(flags.time) flags.botl = 1;
  430. #endif
  431.         if(flags.botl || flags.botlx) bot();
  432.  
  433.         flags.move = 1;
  434.  
  435.         if(multi >= 0 && occupation) {
  436. #ifdef DGK
  437.             abort = 0;
  438.             if (kbhit()) {
  439.                 if ((ch = getchar()) == ABORT)
  440.                     abort++;
  441. # ifdef REDO
  442.                 else
  443.                     pushch(ch);
  444. # endif
  445.             }
  446.             if (abort || monster_nearby())
  447.                 stop_occupation();
  448.             else if ((*occupation)() == 0)
  449.                 occupation = 0;
  450.             if (!(++occtime % 7))
  451.                 (void) fflush(stdout);
  452. #else
  453.             if (monster_nearby())
  454.                 stop_occupation();
  455.             else if ((*occupation)() == 0)
  456.                 occupation = 0;
  457. #endif
  458.             continue;
  459.         }
  460.  
  461.         if(multi > 0) {
  462. #ifdef QUEST
  463.             if(flags.run >= 4) finddir();
  464. #endif
  465.             lookaround();
  466.             if(!multi) {    /* lookaround may clear multi */
  467.                 flags.move = 0;
  468.                 continue;
  469.             }
  470.             if(flags.mv) {
  471.                 if(multi < COLNO && !--multi)
  472.                     flags.mv = flags.run = 0;
  473.                 domove();
  474.             } else {
  475.                 --multi;
  476.                 rhack(save_cm);
  477.             }
  478.         } else if(multi == 0) {
  479.             rhack((char *) 0);
  480.         }
  481.         if(multi && multi%7 == 0)
  482.             (void) fflush(stdout);
  483.     }
  484. }
  485.  
  486. #ifndef DGK
  487. /* This function is unnecessary and incompatible with the #define
  488.  * of glo(x) in config.h -dgk
  489.  */
  490. glo(foo)
  491. register foo;
  492. {
  493.     /* construct the string  xlock.n  */
  494.     register char *tf;
  495.  
  496.     tf = lock;
  497.     while(*tf && *tf != '.') tf++;
  498.     (void) sprintf(tf, ".%d", foo);
  499. }
  500. #endif
  501.  
  502. /*
  503.  * plname is filled either by an option (-u Player  or  -uPlayer) or
  504.  * explicitly (-w implies wizard) or by askname.
  505.  * It may still contain a suffix denoting pl_character.
  506.  */
  507. askname(){
  508. register int c,ct;
  509.     printf("\nWho are you? ");
  510.     (void) fflush(stdout);
  511.     ct = 0;
  512.     while((c = getchar()) != '\n'){
  513. #ifdef MSDOS
  514.         msmsg("%c", c);
  515. #endif
  516.         if(c == EOF) error("End of input\n");
  517.         /* some people get confused when their erase char is not ^H */
  518.         if(c == '\010') {
  519.             if(ct) ct--;
  520.             continue;
  521.         }
  522.         if(c != '-')
  523.         if(c < 'A' || (c > 'Z' && c < 'a') || c > 'z') c = '_';
  524.         if(ct < sizeof(plname)-1) plname[ct++] = c;
  525.     }
  526.     plname[ct] = 0;
  527.     if(ct == 0) askname();
  528. }
  529.  
  530. /*VARARGS1*/
  531. impossible(s,x1,x2)
  532. register char *s;
  533. {
  534.     pline(s,x1,x2);
  535.     pline("Program in disorder - perhaps you'd better Quit.");
  536. }
  537.  
  538. #ifdef CHDIR
  539. chdirx(dir, wr)
  540. char *dir;
  541. boolean wr;
  542. {
  543.  
  544.     if(dir && chdir(dir) < 0) {
  545.         error("Cannot chdir to %s.", dir);
  546.     }
  547.  
  548. #ifdef DGK
  549.     /* Change the default drive as well.
  550.      */
  551.     chdrive(dir);
  552. #endif
  553.  
  554.     /* warn the player if he cannot write the record file */
  555.     /* perhaps we should also test whether . is writable */
  556.     /* unfortunately the access systemcall is worthless */
  557.     if(wr) {
  558.         register fd;
  559.  
  560.         if(dir == NULL)
  561.         dir = ".";
  562.         if((fd = open(RECORD, 2)) < 0) {
  563. #ifdef DGK
  564.         char tmp[PATHLEN];
  565.  
  566.         strcpy(tmp, dir);
  567.         append_slash(tmp);
  568.         msmsg("Warning: cannot write %s%s\n", tmp, RECORD);
  569.         getreturn("to continue");
  570. #else
  571.         printf("Warning: cannot write %s/%s", dir, RECORD);
  572.         getret();
  573. #endif
  574.         } else
  575.         (void) close(fd);
  576.     }
  577. }
  578. #endif /* CHDIR /**/
  579.  
  580. stop_occupation()
  581. {
  582.     extern void pushch();
  583.  
  584.     if(occupation) {
  585.         pline("You stop %s.", occtxt);
  586.         occupation = 0;
  587. #ifdef REDO
  588.         multi = 0;
  589.         pushch(0);        
  590. #endif
  591.     }
  592. }
  593.  
  594. #ifdef DGK
  595. struct finfo    zfinfo = ZFINFO;
  596.  
  597. zero_finfo() {    /* zero "fileinfo" array to prevent crashes on level change */
  598.     int i;
  599.  
  600.     for (i = 0 ; i <= MAXLEVEL; i++)
  601.         fileinfo[i] = zfinfo;
  602. }
  603. #endif
  604.